using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Collections;
using System.Collections.Generic;
using System.Data.Linq;
using System.Linq;

namespace Colman.Messenger.Server
{
    class UdpSocketServer
    {
        public static void Main()
        {
            IPEndPoint localEP = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 9060);

            Dictionary<string, EndPoint> clientsList = new Dictionary<string, EndPoint>();

            Socket server = new Socket(AddressFamily.InterNetwork,
                SocketType.Dgram, ProtocolType.Udp);

            server.Bind(localEP);
            EndPoint remoteEP = new IPEndPoint(IPAddress.Any, 0);

            int recv;
            byte[] data;

            // Main Loop
            while (true)
            {
                try
                {
                    data = new byte[1024];
                    recv = 0;
                    recv = server.ReceiveFrom(data, ref remoteEP);

                    String message = Encoding.ASCII.GetString(data, 0, recv);

                    if (message.Contains("join:"))
                    {
                        HandleClientJoin(clientsList, remoteEP, message);
                    }
                    else if (message.Equals("quit"))
                    {
                        for (int i = 0; i < clientsList.Count; i++)
                        {
                            if (clientsList.ElementAt(i).Value == remoteEP)
                            {
                                clientsList.Remove(clientsList.ElementAt(i).Key);
                                break;
                            }
                        }
                    }
                    else if (message.Equals("contactList"))
                    {
                        for (int i = 0; i < clientsList.Count; i++)
                        {
                            if (clientsList.ElementAt(i).Value == remoteEP)
                            {
                                SendContactList(remoteEP, server, recv, clientsList);
                                break;
                            }
                        }
                    }
                    else
                    {
                        if (message.Contains("messageto:"))
                        {
                            HandlePrivateMessage(clientsList, server, recv, data, message);
                        }
                        else
                        {
                            HandlePublicMessage(clientsList, server, recv, data);
                        }
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }
            }
        }

        private static void SendContactList(EndPoint remoteEP, Socket server, int recv, Dictionary<string, EndPoint> clientsList)
        {
            StringBuilder sb = new StringBuilder("contactList:");

            foreach (var item in clientsList)
            {
                sb.Append(item.Key + ";");
            }

            if (sb.Length > 0)
                sb.Remove(sb.Length - 1, 1);

            server.SendTo(Encoding.ASCII.GetBytes(sb.ToString()), SocketFlags.None, remoteEP);
        }

        private static void HandleClientJoin(Dictionary<string, EndPoint> clientsList , EndPoint remoteEP, string message)
        {
            clientsList.Add(message.Replace("join:", string.Empty).Trim(), remoteEP);
        }

        private static void HandlePublicMessage(Dictionary<string, EndPoint> clientsList, Socket server, int recv, byte[] data)
        {
            int i = 0;
            String Data = Encoding.ASCII.GetString(data);
            while (i < clientsList.Count)
            {
                server.SendTo(Encoding.ASCII.GetBytes(Data), recv, SocketFlags.None, (EndPoint)clientsList.ElementAt(i).Value);
                ++i;
            }
        }

        private static void HandlePrivateMessage(Dictionary<string, EndPoint> clientsList, Socket server, int recv, byte[] data, string message)
        {
            
        }
    }
}